package Stream;

import Lambda.MethodReferences.Employee;
import Lambda.MethodReferences.EmployeeData;
import org.junit.Test;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;

/**
 * @projectName: Java8
 * @package: Stream
 * @className: StreamAPITest2
 * @author: 冷环渊 doomwatcher
 * @description:
 *  测试 Stream的中间操作
 * @date: 2021/12/12 13:12
 * @version: 1.0
 */
public class StreamAPITest2 {

    //filter(Predicate p) 接收 Lambda ， 从流中排除某些元素
    @Test
    public void test1() {
        List<Employee> employeeList = EmployeeData.getEmployees();
        Stream<Employee> stream = employeeList.stream();
        //小练习，查询员工表中薪资大于7000的员工
        System.out.println("filter-------------------");
        stream.filter(e -> e.getSalary() > 7000).forEach(System.out::println);

        /*limit(long maxSize) 截断流，使其元素不超过给定数量
         * 这里我们用  stream 会抛出异常，所以我们直接调用构造方法，每次都会生成新的流
         * */
        System.out.println("limit-------------------");
        employeeList.stream().limit(3).forEach(System.out::println);

        /*    skip(long n)
         *   跳过元素，返回一个扔掉了前 n 个元素的流。若流中元素不足 n 个，则返回一个空流。与 limit(n) 互补
         * */
        System.out.println("skip--------------------");
        employeeList.stream().skip(3).forEach(System.out::println);

        //distinct() 筛选，通过流所生成元素的 hashCode() 和 equals() 去 除重复元素
        System.out.println("distinct----------------");
        employeeList.add(new Employee(1010, "刘强东", 40, 8000));
        employeeList.add(new Employee(1010, "刘强东", 40, 8000));
        employeeList.add(new Employee(1010, "刘强东", 40, 8000));
        employeeList.stream().distinct().forEach(System.out::println);
    }

    /**
     * @author 冷环渊 Doomwatcher
     * @context: 映射
     * @date: 2021/12/12 14:15
     * @param
     * @return: void
     */
    @Test
    public void test2() {
        /*        map(Function f)
         *    接收一个函数作为参数，该函数会被应用到每个元素上，并将其映射成一个新的元素。
         *  映射结果：
         *  aa   --> AA
         *  bb   --> BB
         *  cc   --> CC
         *  dd   --> DD
         * */
        List<String> list = Arrays.asList("aa", "bb", "cc", "dd");
        list.stream().map(str -> str.toUpperCase()).forEach(System.out::println);
        System.out.println();
        List<Employee> employeeList = EmployeeData.getEmployees();
        employeeList.stream().map(Employee::getName).filter(name -> name.length() > 3).forEach(System.out::println);
        System.out.println();

        /*flatMap(Function f)
         * 接收一个函数作为参数，将流中的每个值都换成另一个流，然后把所有流连接成一个流、*/
        //这里是没有用 flatmap的版本 ，我们需要foreach之后再foreach才可以拆分到所有的元素
        Stream<Stream<Character>> streamStream = list.stream().map(StreamAPITest2::fromStringToStream);
        streamStream.forEach(s -> s.forEach(System.out::print));
        System.out.println();
        //使用了 flatmap
        Stream<Character> stream = list.stream().flatMap(StreamAPITest2::fromStringToStream);
        stream.forEach(System.out::print);
    }

    /**
     * @author 冷环渊 Doomwatcher
     * @context:
     * 将字符串中的多个字符构成的集合，转换成对应的Stream的实例
     * @date: 2021/12/12 14:44
     * @param str
     * @return: java.util.stream.Stream<java.lang.Character>
     */
    public static Stream<Character> fromStringToStream(String str) {
        ArrayList<Character> list = new ArrayList<>();
        for (Character c : str.toCharArray()) {
            list.add(c);
        }
        return list.stream();
    }

    /**
     * @author 冷环渊 Doomwatcher
     * @context:
     * =演示 list里放list
     * 【1,2,3，【4,5,6】】
     * 打散开了再放入list
     * 【1,2,3,4,5,6】
     * @date: 2021/12/12 14:33
     * @param
     * @return: void
     */
    @Test
    public void test3() {
        ArrayList list = new ArrayList();
        list.add(1);
        list.add(2);
        list.add(3);
        ArrayList list1 = new ArrayList();
        list1.add(4);
        list1.add(5);
        list1.add(6);
        list.add(list1);
        System.out.println(list);
    }

    /**
     * @author 冷环渊 Doomwatcher
     * @context: 排序
     * @date: 2021/12/12 16:42
     * @param
     * @return: void
     */
    @Test
    public void tset4() {
        //sorted() 产生一个新流，其中按自然顺序排序
        List<Integer> list = Arrays.asList(12, 43, 65, 0, -1, 7);
        list.stream().sorted().forEach(System.out::println);

        /* 这里会出现问题
         * 为什么？
         * 原因：Employee没有实现Comparble接口、
         * List<Employee> employees = EmployeeData.getEmployees();
         * employees.stream().sorted().forEach(System.out::println);
         * */

        //sorted(Comparator com) 产生一个新流，其中按比较器顺序排序
        List<Employee> employees = EmployeeData.getEmployees();
        employees.stream().sorted((e1, e2) -> Integer.compare(e1.getAge(), e2.getAge())).forEach(System.out::println);

        System.out.println();
        //小练习，如果年龄一样就按收入排序
        employees.add(new Employee(1011, "冷环渊", 34, 8000));
        employees.stream().sorted((e1, e2) -> {
            int agevalue = Integer.compare(e1.getAge(), e2.getAge());
            if (agevalue != 0) {
                return agevalue;
            } else {
                return -Double.compare(e1.getSalary(), e2.getSalary());
            }
        }).forEach(System.out::println);

    }
}
